package com.jsmile.cloud.tradecenter.order.model;

import java.util.Date;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.jsmile.cloud.accountcenter.api.enums.PayTypeEnum;
import com.jsmile.cloud.goodscenter.api.enums.DeliveryTypeEnum;
import com.jsmile.cloud.goodscenter.api.res.ResSku;
import com.jsmile.cloud.tradecenter.api.enums.OrderStatusEnum;
import com.jsmile.cloud.tradecenter.api.enums.PayMethodEnum;
import com.jsmile.cloud.tradecenter.api.enums.RefundFlagEnum;
import com.jsmile.cloud.tradecenter.api.req.ReqOrderCreate;
import com.jsmile.cloud.tradecenter.api.req.ReqOrderFinish;
import com.jsmile.cloud.tradecenter.api.req.SplitOrder;
import com.jsmile.cloud.tradecenter.express.model.OrderExpress;
import com.jsmile.cloud.tradecenter.order.event.*;
import com.jsmile.cloud.tradecenter.order.factory.OrderCheckKit;
import com.jsmile.mail.security.event.DomainEventPublisher;
import com.jsmile.mall.api.exception.ExceptionKit;
import com.jsmile.mall.api.kit.StrKit;

import cn.hutool.core.bean.BeanUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author 龚亮
 * @version 1.0
 * @desc 为了薪资破万，还是睡一会儿吧...!
 * @date 2019年12月19日 02:56:26
 */
@ApiModel
@Data
@TableName("t_order")
public class Order extends Model<Order> {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "id")
    @TableId(value = "id", type = IdType.INPUT)
    private Long id;
    @ApiModelProperty(value = "用户id")
    private Long userId;
    @ApiModelProperty(value = "订单类型 1平台订单 2自营订单 3拼团订单 4秒杀订单 5.限时购")
    private Integer orderType;
    @ApiModelProperty(value = "活动id")
    private Long activityId;
    @ApiModelProperty(value = "待支付:1，待发货:2，待签收:3，已完成:4，已关闭:5")
    private Integer orderStatus;
    @ApiModelProperty(value = "实付金额")
    private Long actuallyPayAmount;
    @ApiModelProperty(value = "余额支付金额")
    private Long balanceAmount;
    @ApiModelProperty(value = "商品总金额")
    private Long productAmount;
    @ApiModelProperty(value = "折扣金额:优惠券,活动,积分抵扣之和")
    private Long discountAmount;
    @ApiModelProperty(value = "优惠券金额")
    private Long ticketDisamt;
    @ApiModelProperty(value = "活动优惠金额")
    private Long promotionDisamt;
    @ApiModelProperty(value = "积分抵扣金额")
    private Long pointDisamt;
    @ApiModelProperty(value = "运费")
    private Long logisticsFee;
    @ApiModelProperty(value = "付款方式，1-余额支付  2微信支付  3支付宝支付")
    private Integer payMethod;
    @ApiModelProperty(value = "发货类型：1自提，2快递")
    private Integer deliveryType;
    @ApiModelProperty(value = "下单时间")
    private Date createTime;
    @ApiModelProperty(value = "支付时间")
    private Date payTime;
    @ApiModelProperty(value = "发货时间")
    private Date deliveryTime;
    @ApiModelProperty(value = "完成时间")
    private Date finishTime;
    @ApiModelProperty(value = "关闭时间")
    private Date closeTime;
    @ApiModelProperty(value = "取消类型 1用户取消 2商家取消")
    private Integer cancelType;
    @ApiModelProperty(value = "取消原因")
    private String cancelReason;
    @ApiModelProperty(value = "更新时间")
    private Date updateTime;
    @ApiModelProperty(value = "退款标记（0未退款，1退款）")
    private Integer refundFlag;
    @ApiModelProperty(value = "退款时间")
    private Date refundTime;
    @ApiModelProperty(value = "删除标记")
    @TableLogic
    private Integer delFlag;
    @ApiModelProperty(value = "支付备注")
    private String payRemark;
    @ApiModelProperty(value = "订单备注")
    private String orderRemark;
    @ApiModelProperty(value = "付款截止时间")
    private Date payDeadlineTime;
    @ApiModelProperty(value = "自动收货任务处罚的日期，格式如：20180901")
    private String autoFinishDate;
    @ApiModelProperty(value = "取货码")
    private String orderCode;
    @ApiModelProperty(value = "店铺ID")
    private Long shopId;
    @ApiModelProperty(value = "租户id")
    private Long tenantId;
    @ApiModelProperty(value = "商户id")
    private Long merchantId;
    @ApiModelProperty(value = "供应商id")
    private Long supplyId;
    @ApiModelProperty(value = "平台id")
    private Integer platformId;
    @ApiModelProperty(value = "业务id")
    private Integer bizCode;
    @ApiModelProperty(value = "第三方订单编号")
    private String thirdOrderNo;

    @TableField(exist = false)
    @ApiModelProperty(value = "订单地址")
    private OrderAddress orderAddress;
    @TableField(exist = false)
    @ApiModelProperty(value = "订单优惠")
    private List<OrderDiscount> orderDiscounts;
    @TableField(exist = false)
    @ApiModelProperty(value = "订单商品")
    private List<OrderProduct> orderProducts;
    @ApiModelProperty(value = "物流信息")
    private List<OrderExpress> orderExpresses;

    // todo 订单创建
    public static Order create(OrderCheckKit orderCheckKit, SplitOrder splitOrder, Map<Long, ResSku> skuMap, List<ReqOrderCreate.OrderSku> orderSkus) {
        Order order = BeanUtil.toBean(orderCheckKit.getReqOrderCreate(), Order.class);
        // if (PayTypeEnum.hasWxPay(orderCheckKit.getReqOrderCreate().getPayType())) {
        // order.setPayMethod(PayMethodEnum.WX.getValue());
        // } else if (PayTypeEnum.hasZfbPay(orderCheckKit.getReqOrderCreate().getPayType())) {
        // order.setPayMethod(PayMethodEnum.ZFB.getValue());
        // }
        order.setId(orderCheckKit.getOrderNos().poll());
        order.setUserId(orderCheckKit.getReqOrderCreate().getCurUserId());
        order.setTenantId(orderCheckKit.getReqOrderCreate().getCurTenantId());
        order.setCreateTime(new Date());
        order.setShopId(splitOrder.getShopId());
        order.setSupplyId(splitOrder.getSupplyId());
        order.setDeliveryType(splitOrder.getDeliveryType());
        order.setOrderRemark(orderSkus.get(0).getOrderRemark());
        order.setOrderAddress(OrderAddress.create(order, orderCheckKit.getReqOrderCreate().getAddressId()));
        order.setOrderProducts(OrderProduct.create(order, orderSkus, skuMap));
        order.setOrderDiscounts(OrderDiscount.create(order));
        order.setActuallyPayAmount(order.getOrderProducts().stream().mapToLong(OrderProduct::getActuallyPayAmount).sum());
        order.setBalanceAmount(order.getOrderProducts().stream().mapToLong(OrderProduct::getBalanceAmount).sum());
        order.setPromotionDisamt(order.getOrderProducts().stream().mapToLong(OrderProduct::getPromotionDisamt).sum());
        order.setTicketDisamt(order.getOrderProducts().stream().mapToLong(OrderProduct::getTicketDisamt).sum());
        order.setPointDisamt(order.getOrderProducts().stream().mapToLong(OrderProduct::getPointDisamt).sum());
        order.setProductAmount(order.getOrderProducts().stream().mapToLong(OrderProduct::getProductAmount).sum());
        if (orderCheckKit.getHasEvent()) {
            DomainEventPublisher.publish(new OrderCreateEvent(order));
        }
        if (order.getActuallyPayAmount().longValue() == 0L) {
            order.setPayMethod(PayMethodEnum.BALANCE.getValue());
        }
        return order;
    }

    // TODO 订单支付
    public void paySuccess(int payType) {
        ExceptionKit.checkArgument(this.getOrderStatus() != OrderStatusEnum.TO_PAY.getValue(), "订单状态不是待付款!");
        this.setPayTime(new Date());
        if (DeliveryTypeEnum.EXPRESS.getValue() == this.getDeliveryType()) {
            this.setOrderStatus(OrderStatusEnum.TO_DELIVERY.getValue());
        } else {
            this.setDeliveryTime(new Date());
            this.setOrderStatus(OrderStatusEnum.TO_SIGN.getValue());
            DomainEventPublisher.publish(new OrderSignEvent(this));
        }
        if (PayTypeEnum.hasWxPay(payType)) {
            this.setPayMethod(PayMethodEnum.WX.getValue());
        } else if (PayTypeEnum.hasZfbPay(payType)) {
            this.setPayMethod(PayMethodEnum.ZFB.getValue());
        }
        this.setUpdateTime(new Date());
        DomainEventPublisher.publish(new OrderPayEvent(this));
    }

    // TODO 订单完成
    public void finishOrder(ReqOrderFinish reqOrderFinish) {
        ExceptionKit.checkArgument(this.getOrderStatus() < OrderStatusEnum.TO_SIGN.getValue(), "订单状态不是待签收!");
        if (StrKit.notBlank(reqOrderFinish.getOrderCode())) {// 提货
            ExceptionKit.checkArgument(!reqOrderFinish.getOrderCode().equals(this.getOrderCode()), "提货码不对!");
            ExceptionKit.checkArgument(!reqOrderFinish.getShopId().equals(this.getShopId()), "请到对应的店铺核销!");
        }
        this.setUpdateTime(new Date());
        this.setFinishTime(new Date());
        this.setOrderStatus(OrderStatusEnum.FINISH.getValue());
        DomainEventPublisher.publish(new OrderFinishEvent(this));
    }

    // TODO 订单发货
    public void deliveyOrder() {
        ExceptionKit.checkArgument(this.getOrderStatus() != OrderStatusEnum.TO_DELIVERY.getValue(), "订单状态不是待发货!");
        this.setOrderStatus(OrderStatusEnum.TO_SIGN.getValue());
        this.setUpdateTime(new Date());
        DomainEventPublisher.publish(new OrderSignEvent(this));
    }

    // TODO 取消订单/关闭订单
    public void cancelOrder() {
        ExceptionKit.checkArgument(this.getOrderStatus() > OrderStatusEnum.TO_DELIVERY.getValue(), "付款成功的订单不能取消订单!");
        this.setOrderStatus(OrderStatusEnum.CLOSE.getValue());
        this.setUpdateTime(new Date());
        DomainEventPublisher.publish(new OrderCloseEvent(this));
    }

    public void refund() {
        this.setOrderStatus(OrderStatusEnum.CLOSE.getValue());
        this.setRefundFlag(RefundFlagEnum.REFUND.getValue());
        this.setUpdateTime(new Date());
        DomainEventPublisher.publish(new OrderRefundEvent(this));
    }

}
